home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / game / shoot / ADoom_src_1_2.lha / ADoom_src / w_wad.c < prev    next >
C/C++ Source or Header  |  1998-02-18  |  11KB  |  604 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    Handles WAD file header, directory, lump I/O.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24.  
  25. static const char
  26. rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
  27.  
  28.  
  29. #ifdef NORMALUNIX
  30. #ifndef __SASC
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <malloc.h>
  36. #include <fcntl.h>
  37. #include <sys/stat.h>
  38. #include <alloca.h>
  39. #define O_BINARY        0
  40. #else
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include <stat.h>
  46. #endif
  47. #endif
  48.  
  49. #include "doomdef.h"
  50. #include "doomtype.h"
  51. #include "m_swap.h"
  52. #include "i_system.h"
  53. #include "z_zone.h"
  54.  
  55. #ifdef __GNUG__
  56. #pragma implementation "w_wad.h"
  57. #endif
  58. #include "w_wad.h"
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65. //
  66. // GLOBALS
  67. //
  68.  
  69. // Location of each lump on disk.
  70. lumpinfo_t*        lumpinfo;        
  71. int            numlumps;
  72.  
  73. void**            lumpcache;
  74.  
  75.  
  76. #ifndef __SASC
  77. #define strcmpi    strcasecmp
  78.  
  79. void strupr (char* s)
  80. {
  81.     while (*s) { *s = toupper(*s); s++; }
  82. }
  83. #endif
  84.  
  85. int filelength (int handle) 
  86.     struct stat    *fileinfo;
  87.     int size;
  88.     
  89.     if ((fileinfo = malloc (sizeof(struct stat))) == NULL ||
  90.         fstat (handle,fileinfo) == -1)
  91.     I_Error ("Error fstating");
  92.     size = fileinfo->st_size;
  93.     free (fileinfo);
  94.  
  95.     return size;
  96. }
  97.  
  98.  
  99. void
  100. ExtractFileBase
  101. ( char*        path,
  102.   char*        dest )
  103. {
  104.     char*    src;
  105.     int        length;
  106.  
  107.     src = path + strlen(path) - 1;
  108.     
  109.     // back up until a \ or the start
  110.     while (src != path
  111.        && *(src-1) != '\\'
  112.        && *(src-1) != '/')
  113.     {
  114.     src--;
  115.     }
  116.     
  117.     // copy up to eight characters
  118.     memset (dest,0,8);
  119.     length = 0;
  120.     
  121.     while (*src && *src != '.')
  122.     {
  123.     if (++length == 9)
  124.         I_Error ("Filename base of %s >8 chars",path);
  125.  
  126.     *dest++ = toupper((int)*src++);
  127.     }
  128. }
  129.  
  130.  
  131.  
  132.  
  133.  
  134. //
  135. // LUMP BASED ROUTINES.
  136. //
  137.  
  138. //
  139. // W_AddFile
  140. // All files are optional, but at least one file must be
  141. //  found (PWAD, if all required lumps are present).
  142. // Files with a .wad extension are wadlink files
  143. //  with multiple lumps.
  144. // Other files are single lumps with the base filename
  145. //  for the lump name.
  146. //
  147. // If filename starts with a tilde, the file is handled
  148. //  specially to allow map reloads.
  149. // But: the reload feature is a fragile hack...
  150.  
  151. int            reloadlump;
  152. char*            reloadname;
  153.  
  154.  
  155. void W_AddFile (char *filename)
  156. {
  157.     wadinfo_t        header;
  158.     lumpinfo_t*        lump_p;
  159.     unsigned        i;
  160.     FILE        *handle;
  161.     int            length;
  162.     int            startlump;
  163.     filelump_t*        fileinfo = NULL;
  164.     filelump_t        singleinfo, *fi;
  165.     FILE        *storehandle;
  166.     int                 fileinfo_allocated = 0;
  167.     
  168.     // open the file and add to directory
  169.  
  170.     // handle reload indicator.
  171.     if (filename[0] == '~')
  172.     {
  173.     filename++;
  174.     reloadname = filename;
  175.     reloadlump = numlumps;
  176.     }
  177.         
  178.     if ( (handle = fopen (filename,"r")) == NULL)
  179.     {
  180.     printf (" couldn't open %s\n",filename);
  181.     return;
  182.     }
  183.  
  184.     printf (" adding %s\n",filename);
  185.     startlump = numlumps;
  186.     
  187.     if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
  188.     {
  189.     // single lump file
  190.     fileinfo = &singleinfo;
  191.     singleinfo.filepos = 0;
  192.     singleinfo.size = SWAPLONG(filelength(fileno(handle)));
  193.     ExtractFileBase (filename, singleinfo.name);
  194.     numlumps++;
  195.     }
  196.     else 
  197.     {
  198.     // WAD file
  199.     fread (&header, 1, sizeof(header), handle);
  200.     if (strncmp(header.identification,"IWAD",4))
  201.     {
  202.         // Homebrew levels?
  203.         if (strncmp(header.identification,"PWAD",4))
  204.         {
  205.         I_Error ("Wad file %s doesn't have IWAD "
  206.              "or PWAD id\n", filename);
  207.         }
  208.         
  209.         // ???modifiedgame = true;        
  210.     }
  211.     header.numlumps = SWAPLONG(header.numlumps);
  212.     header.infotableofs = SWAPLONG(header.infotableofs);
  213.     length = header.numlumps*sizeof(filelump_t);
  214.     fileinfo = malloc (length);
  215.         fileinfo_allocated = 1;
  216.     fseek (handle, header.infotableofs, SEEK_SET);
  217.     fread (fileinfo, 1, length, handle);
  218.     numlumps += header.numlumps;
  219.     }
  220.  
  221.     
  222.     // Fill in lumpinfo
  223.     lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
  224.  
  225.     if (!lumpinfo)
  226.     I_Error ("Couldn't realloc lumpinfo");
  227.  
  228.     lump_p = &lumpinfo[startlump];
  229.     
  230.     storehandle = reloadname ? NULL : handle;
  231.  
  232.     fi = fileinfo;
  233.     for (i=startlump ; i<numlumps ; i++,lump_p++, fi++)
  234.     {
  235.     lump_p->handle = storehandle;
  236.     lump_p->position = SWAPLONG(fi->filepos);
  237.     lump_p->size = SWAPLONG(fi->size);
  238.     strncpy (lump_p->name, fi->name, 8);
  239.     }
  240.     
  241.     if (reloadname)
  242.     fclose (handle);
  243.     if (fileinfo_allocated)
  244.         free (fileinfo);
  245. }
  246.  
  247.  
  248.  
  249.  
  250. //
  251. // W_Reload
  252. // Flushes any of the reloadable lumps in memory
  253. //  and reloads the directory.
  254. //
  255. void W_Reload (void)
  256. {
  257.     wadinfo_t        header;
  258.     int            lumpcount;
  259.     lumpinfo_t*        lump_p;
  260.     unsigned        i;
  261.     FILE        *handle;
  262.     int            length;
  263.     filelump_t*        fileinfo = NULL;
  264.     filelump_t*         fi;
  265.  
  266.     if (!reloadname)
  267.     return;
  268.  
  269.     if ( (handle = fopen (reloadname,"r")) == NULL)
  270.     I_Error ("W_Reload: couldn't open %s",reloadname);
  271.  
  272.     fread (&header, 1, sizeof(header), handle);
  273.     lumpcount = SWAPLONG(header.numlumps);
  274.     header.infotableofs = SWAPLONG(header.infotableofs);
  275.     length = lumpcount*sizeof(filelump_t);
  276.     fileinfo = malloc (length);
  277.     fseek (handle, header.infotableofs, SEEK_SET);
  278.     fread (fileinfo, 1, length, handle);
  279.  
  280.     // Fill in lumpinfo
  281.     lump_p = &lumpinfo[reloadlump];
  282.     
  283.     fi = fileinfo;
  284.     for (i=reloadlump ;
  285.      i<reloadlump+lumpcount ;
  286.      i++,lump_p++, fi++)
  287.     {
  288.     if (lumpcache[i])
  289.         Z_Free (lumpcache[i]);
  290.  
  291.     lump_p->position = SWAPLONG(fi->filepos);
  292.     lump_p->size = SWAPLONG(fi->size);
  293.     }
  294.     
  295.     fclose (handle);
  296.     if (fileinfo != NULL)
  297.        free (fileinfo);
  298. }
  299.  
  300.  
  301.  
  302. //
  303. // W_InitMultipleFiles
  304. // Pass a null terminated list of files to use.
  305. // All files are optional, but at least one file
  306. //  must be found.
  307. // Files with a .wad extension are idlink files
  308. //  with multiple lumps.
  309. // Other files are single lumps with the base filename
  310. //  for the lump name.
  311. // Lump names can appear multiple times.
  312. // The name searcher looks backwards, so a later file
  313. //  does override all earlier ones.
  314. //
  315. void W_InitMultipleFiles (char** filenames)
  316. {    
  317.     int        size;
  318.     
  319.     // open all the files, load headers, and count lumps
  320.     numlumps = 0;
  321.  
  322.     // will be realloced as lumps are added
  323.     lumpinfo = malloc(1);    
  324.  
  325.     for ( ; *filenames ; filenames++)
  326.     W_AddFile (*filenames);
  327.  
  328.     if (!numlumps)
  329.     I_Error ("W_InitFiles: no files found");
  330.     
  331.     // set up caching
  332.     size = numlumps * sizeof(*lumpcache);
  333.     lumpcache = malloc (size);
  334.     
  335.     if (!lumpcache)
  336.     I_Error ("Couldn't allocate lumpcache");
  337.  
  338.     memset (lumpcache,0, size);
  339. }
  340.  
  341.  
  342.  
  343.  
  344. //
  345. // W_InitFile
  346. // Just initialize from a single file.
  347. //
  348. void W_InitFile (char* filename)
  349. {
  350.     char*    names[2];
  351.  
  352.     names[0] = filename;
  353.     names[1] = NULL;
  354.     W_InitMultipleFiles (names);
  355. }
  356.  
  357.  
  358.  
  359. //
  360. // W_NumLumps
  361. //
  362. int W_NumLumps (void)
  363. {
  364.     return numlumps;
  365. }
  366.  
  367.  
  368.  
  369. //
  370. // W_CheckNumForName
  371. // Returns -1 if name not found.
  372. //
  373.  
  374. int W_CheckNumForName (char* name)
  375. {
  376.     union {
  377.     char    s[9];
  378.     int    x[2];
  379.     
  380.     } name8;
  381.     
  382.     int        v1;
  383.     int        v2;
  384.     lumpinfo_t*    lump_p;
  385.  
  386.     // make the name into two integers for easy compares
  387.     strncpy (name8.s,name,8);
  388.  
  389.     // in case the name was a fill 8 chars
  390.     name8.s[8] = 0;
  391.  
  392.     // case insensitive
  393.     strupr (name8.s);        
  394.  
  395.     v1 = name8.x[0];
  396.     v2 = name8.x[1];
  397.  
  398.  
  399.     // scan backwards so patch lump files take precedence
  400.     lump_p = lumpinfo + numlumps;
  401.  
  402.     while (lump_p-- != lumpinfo)
  403.     {
  404.     if ( *(int *)lump_p->name == v1
  405.          && *(int *)&lump_p->name[4] == v2)
  406.     {
  407.         return lump_p - lumpinfo;
  408.     }
  409.     }
  410.  
  411.     // TFB. Not found.
  412.     return -1;
  413. }
  414.  
  415.  
  416.  
  417.  
  418. //
  419. // W_GetNumForName
  420. // Calls W_CheckNumForName, but bombs out if not found.
  421. //
  422. int W_GetNumForName (char* name)
  423. {
  424.     int    i;
  425.  
  426.     i = W_CheckNumForName (name);
  427.     
  428.     if (i == -1)
  429.       I_Error ("W_GetNumForName: %s not found!", name);
  430.       
  431.     return i;
  432. }
  433.  
  434.  
  435. //
  436. // W_LumpLength
  437. // Returns the buffer size needed to load the given lump.
  438. //
  439. int W_LumpLength (int lump)
  440. {
  441.     if (lump >= numlumps)
  442.     I_Error ("W_LumpLength: %i >= numlumps",lump);
  443.  
  444.     return lumpinfo[lump].size;
  445. }
  446.  
  447.  
  448.  
  449. //
  450. // W_ReadLump
  451. // Loads the lump into the given buffer,
  452. //  which must be >= W_LumpLength().
  453. //
  454. void
  455. W_ReadLump
  456. ( int        lump,
  457.   void*        dest )
  458. {
  459.     int        c;
  460.     lumpinfo_t*    l;
  461.     FILE    *handle;
  462.     
  463.     if (lump >= numlumps)
  464.     I_Error ("W_ReadLump: %i >= numlumps",lump);
  465.  
  466.     l = lumpinfo+lump;
  467.     
  468.     // ??? I_BeginRead ();
  469.     
  470.     if (l->handle == NULL)
  471.     {
  472.     // reloadable file, so use open / read / close
  473.     if ( (handle = fopen (reloadname,"r")) == NULL)
  474.         I_Error ("W_ReadLump: couldn't open %s",reloadname);
  475.     }
  476.     else
  477.     handle = l->handle;
  478.         
  479.     fseek (handle, l->position, SEEK_SET);
  480.     c = fread (dest, 1, l->size, handle);
  481.  
  482.     if (c < l->size)
  483.     I_Error ("W_ReadLump: only read %i of %i on lump %i",
  484.          c,l->size,lump);    
  485.  
  486.     if (l->handle == NULL)
  487.     fclose (handle);
  488.         
  489.     // ??? I_EndRead ();
  490. }
  491.  
  492.  
  493.  
  494.  
  495. #ifndef AMIGA
  496. //
  497. // W_CacheLumpNum
  498. //
  499. void*
  500. W_CacheLumpNum
  501. ( int        lump,
  502.   int        tag )
  503. {
  504.     byte*    ptr;
  505.  
  506.     if ((unsigned)lump >= numlumps)
  507.     I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  508.         
  509.     if (!lumpcache[lump])
  510.     {
  511.     // read the lump in
  512.     
  513.     //printf ("cache miss on lump %i\n",lump);
  514.     ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
  515.     W_ReadLump (lump, lumpcache[lump]);
  516.     }
  517.     else
  518.     {
  519.     //printf ("cache hit on lump %i\n",lump);
  520.     Z_ChangeTag (lumpcache[lump],tag);
  521.     }
  522.     
  523.     return lumpcache[lump];
  524. }
  525. #endif
  526.  
  527.  
  528.  
  529. //
  530. // W_CacheLumpName
  531. //
  532. void*
  533. W_CacheLumpName
  534. ( char*        name,
  535.   int        tag )
  536. {
  537.     return W_CacheLumpNum (W_GetNumForName(name), tag);
  538. }
  539.  
  540.  
  541. //
  542. // W_Profile
  543. //
  544. FAR int        info[2500][10];
  545. int        profilecount;
  546.  
  547. void W_Profile (void)
  548. {
  549.     int        i;
  550.     memblock_t*    block;
  551.     void*    ptr;
  552.     char    ch;
  553.     FILE*    f;
  554.     int        j;
  555.     char    name[9];
  556.     
  557.     
  558.     for (i=0 ; i<numlumps ; i++)
  559.     {    
  560.     ptr = lumpcache[i];
  561.     if (!ptr)
  562.     {
  563.         ch = ' ';
  564.         continue;
  565.     }
  566.     else
  567.     {
  568.         block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  569.         if (block->tag < PU_PURGELEVEL)
  570.         ch = 'S';
  571.         else
  572.         ch = 'P';
  573.     }
  574.     info[i][profilecount] = ch;
  575.     }
  576.     profilecount++;
  577.     
  578.     f = fopen ("waddump.txt","w");
  579.     name[8] = 0;
  580.  
  581.     for (i=0 ; i<numlumps ; i++)
  582.     {
  583.     memcpy (name,lumpinfo[i].name,8);
  584.  
  585.     for (j=0 ; j<8 ; j++)
  586.         if (!name[j])
  587.         break;
  588.  
  589.     for ( ; j<8 ; j++)
  590.         name[j] = ' ';
  591.  
  592.     fprintf (f,"%s ",name);
  593.  
  594.     for (j=0 ; j<profilecount ; j++)
  595.         fprintf (f,"    %c",info[i][j]);
  596.  
  597.     fprintf (f,"\n");
  598.     }
  599.     fclose (f);
  600. }
  601.  
  602.  
  603.